/*
 *	ApOS (Another Project software for s3c2410)
 *	
 *	This program is free software; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License version 2 as
 *	published by the Free Software Foundation.
 *			
 *
 */
#include "../include/s3c2410/s3c2410.h"
#include "../include/s3c2410/lcd.h"

extern con_bkcolor;
struct lcd_control_obj lcd_control_obj;

void lcd_scr_init()
{
	clear_screen(con_bkcolor);
	
	*lcd_control_obj.saddr1=(((unsigned int)(lcd_control_obj.framebuffer)>>22)<<21)|M5D(((unsigned int)lcd_control_obj.framebuffer)>>1);
	*lcd_control_obj.saddr2=M5D(((unsigned int)(lcd_control_obj.framebuffer)+(SCR_XSIZE_TFT*LCD_YSIZE_TFT*2))>>1);
	
}

void lcd_config()
{
	*lcd_control_obj.con1=(CLKVAL_TFT<<8)|(MMODE_EACH_FRAME<<7)|(TFT_LCD_PANEL<<5)|(MODE_16_BPP_TFT<<1)|ENVID;
	*lcd_control_obj.con2=(VBPD<<24)|(LINEVAL_TFT<<14)|(VFPD<<6)|(VSPW);
	*lcd_control_obj.con3=(HBPD<<19)|(HOZVAL_TFT<<8)|(HFPD);
	*lcd_control_obj.con4=(MVAL<<8)|(HSPW);
	*lcd_control_obj.con5=(0<<11)|(1<<9)|(1<<8);
	
	*lcd_control_obj.saddr1=(((unsigned int)(lcd_control_obj.framebuffer)>>22)<<21)|M5D(((unsigned int)lcd_control_obj.framebuffer)>>1);
	*lcd_control_obj.saddr2=M5D(((unsigned int)(lcd_control_obj.framebuffer)+(SCR_XSIZE_TFT*LCD_YSIZE_TFT*2))>>1);
	*lcd_control_obj.saddr3=(((SCR_XSIZE_TFT-LCD_XSIZE_TFT)/1)<<11)|(LCD_XSIZE_TFT/1);
	
	*lcd_control_obj.intmsk|=(FIWSEL<<2)|(INT_FRSYN<<1)|(INT_FICNT);
	*lcd_control_obj.lpcsel&=DISABLE_LPC3600;
	*lcd_control_obj.tpal=DISABLE_TEMP_PALETTE;
}

void lcd_power_on()
{
	*(lcd_control_obj.con5)|=(LCD_POWER_ON<<3);	// Enable power
	*(lcd_control_obj.con5)&=(~(INVLEND_INVERTED<<5));	// INVPWREN
}

void lcd_envid_on_off(int onoff)
{
	if(onoff==1)
		*lcd_control_obj.con1|=1;			// ENVID=ON
	else
		*lcd_control_obj.con1&=0x3fffe;		// ENVID Off
}

void lcd_on()
{
	lcd_config();
	lcd_power_on();
	lcd_envid_on_off(1);
	clear_screen(RGB(0,0,0));
}

void set_pixel(unsigned int x,unsigned int y,unsigned short color)
{
	(lcd_control_obj.framebuffer)[(y)][(x)/2]=( (lcd_control_obj.framebuffer)[(y)][x/2]
        & ~(0xffff0000>>((x)%2)*16) ) | ( (color&0x0000ffff)<<((2-1-((x)%2))*16));
}

void clear_screen(unsigned short _color)
{
	unsigned int tmp=_color<<16|_color;
	unsigned int buf_start	=LCDFRAMEBUFFER;
	unsigned int buf_end	=LCDFRAMEBUFFER+640*480*4;
	asm volatile(
		"ldr r0,%1 \n\t"
		"ldr r1,%2 \n\t"
		"ldr r2,%0 \n\t"
		"1: str r2,[r0],#4 \n\t"
		"cmp r0,r1 \n\t"
		"bne 	1b \n\t"
		:
		:"m"(tmp),"m"(buf_start),"m"(buf_end)
		:"r0","r1","r2"
	);
}

void lcd_control_obj_init(struct lcd_control_obj *lco)
{
	lco->con1	=&rLCDCON1;
	lco->con2	=&rLCDCON2;
	lco->con3	=&rLCDCON3;
	lco->con4	=&rLCDCON4;
	lco->con5	=&rLCDCON5;
	lco->saddr1	=&rLCDSADDR1;
	lco->saddr2	=&rLCDSADDR2;
	lco->saddr3	=&rLCDSADDR3;
	lco->redlut	=&rREDLUT;
	lco->greedlut	=&rGREENLUT;
	lco->bluelut	=&rBLUELUT;
	lco->dithmode	=&rDITHMODE;
	lco->tpal	=&rTPAL;
	lco->intpnd	=&rLCDINTPND;
	lco->srcpnd	=&rLCDSRCPND;
	lco->intmsk	=&rLCDINTMSK;
	lco->lpcsel	=&rLPCSEL;
	lco->framebuffer=(unsigned int (*)[SCR_XSIZE_TFT/2])LCDFRAMEBUFFER;
	
}